/**
 * @author: Gene
 * @age: 永远18岁的美少年
 * @Email： yangjianyun@58.com
 * @date: 2021-12-04 10:12:19
 * @description: ts 中的接口
 *
 *  接口的特性:
 *      同名的接口,可以写多个, 类型会自动合并
 */

export {}

// 1. 接口描述对象的形状
interface ISpeakable {
    name: string;

    speak(): void
}

let speakMan: ISpeakable = {
    name: "Gene",
    speak() {
    }
}

// 2. 描述行为的抽象
interface IEatable {
    eat(): void
}

// 类来实现接口, 接口里的所有方法
class Person implements ISpeakable, IEatable {
    name: string

    eat(): void {
    }

    speak(): void {
    }
}

/** ================ 接口中的定义任意属性 ====================*/
// 任意属性, 那么约束 IPerson的类,或者对象,就可以添加 接口中还未定义的 属性
interface IPerson {
    readonly  id: number,
    name: string;

    [key: string]: any
}

let p: IPerson = {
    id: 0,
    name: "",
    age: 10
}


/** ================= 接口的继承 ======================*/
interface ISpeakable {
    speak(): void
}

interface ISpeakChinese extends ISpeakable {
    speakChinese(): void
}

class ChineseMan implements ISpeakChinese {
    name: string

    speak(): void {
    }

    speakChinese(): void {
    }

}

/** ============= readonly 属性 ========*/
interface IPerson3 {
    readonly id: number
}

let p2: IPerson3 = {id: 1}

/** ============================ 函数类型接口  ========================*/
interface IDiscount {
    (price: number): number
}

const discount: IDiscount = (price: number): number => {
    return price * 8
}

/** ============= 可索引接口 interface ===================*/
// 接口可以对数组 对对象进行约束
interface IUser {
    [indexxxx: number]: string
}

let user: IUser = {
    0: "0",
    1: "1"
}
let userArr: IUser = ["1", "2", "3"]

/** ===================== 如何用接口去约束我们的类 -----------------------*/
interface ISpeakable {
    speak(): void
}

// 构造函数类型
class Animal {
    constructor(public name: string) {

    }
}

// 如果接口是修饰的普通函数
// 加上 new 之后就是用来描述类的构造函数
interface IWithNameClass {
    // (name: string): any // 不加 new 是修饰的普通函数
    new(name: string): any // 加上 new 之后, 修饰的是类
}

let wc: IWithNameClass = Animal